package com.oromwin.repos.common;

import java.io.IOException;
import java.util.Properties;

import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.commons.logging.Log;

public enum ReposConfig {
    INSTANCE;
    @SuppressWarnings("unused")
    private final static Log log = Logger.getLog(ReposConfig.class);
    // database
    private String reposDatabaseDriver = null;
    private String reposDatabaseUri = null;
    private String reposDatabaseHost = null;
    private int reposDatabasePort = 0;
    private String reposDatabaseName = null;
    private String reposDatabaseUser = null;
    private String reposDatabasePasswd = null;
    // local
    private long reposLocalDiskUsageReserved = 0;
    // socket server
    private String reposSocketServerIP = "";
    private int reposSocketServerPort = 0;
    private int reposSocketServerPoolSize = 0;
    private int reposSocketIOBuffSize = 0;
    private int reposSocketServerTimeout = 0;
    // socket client
    private int reposSocketClientTimeout = 0;
    // http server
    private String reposHttpServerIP = "";
    private int reposHttpServerPort = 0;

    private ReposConfig() {
        loadProperties(Common.DEFAULT_PROPERTIES);
    }
    public static ReposConfig getInstance() {
        return INSTANCE;
    }
    
    public String getReposDatabaseDriver() {
        return reposDatabaseDriver;
    }
    public String getReposDatabaseUri() {
        return reposDatabaseUri;
    }
    public String getReposDatabaseHost() {
        return reposDatabaseHost;
    }
    public int getReposDatabasePort() {
        return reposDatabasePort;
    }
    public String getReposDatabaseName() {
        return reposDatabaseName;
    }
    public String getReposDatabaseUser() {
        return reposDatabaseUser;
    }
    public String getReposDatabasePasswd() {
        return reposDatabasePasswd;
    }
    public long getReposLocalDiskUsageReserved() {
        return reposLocalDiskUsageReserved;
    }
    public String getReposSocketServerIP() {
        return reposSocketServerIP;
    }
    public int getReposSocketPort() {
        return reposSocketServerPort;
    }
    public int getReposSocketServerPoolSize() {
        return reposSocketServerPoolSize;
    }
    public int getReposSocketIOBuffSize() {
        return reposSocketIOBuffSize;
    }
    public int getReposSocketClientTimeout() {
        return reposSocketClientTimeout;
    }
    public int getReposSocketServerTimeout() {
        return reposSocketServerTimeout;
    }
    public String getReposHttpServerIP() {
        return reposHttpServerIP;
    }
    public void setReposHttpServerIP(String reposHttpServerIP) {
        this.reposHttpServerIP = reposHttpServerIP;
    }
    public int getReposHttpServerPort() {
        return reposHttpServerPort;
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("-------------------- Repository Config --------------------\n");
        sb.append(String.format("repos.db.driver=%s\n", reposDatabaseDriver));
        sb.append(String.format("repos.db.uri=%s\n", reposDatabaseUri));
        sb.append(String.format("repos.db.host=%s\n", reposDatabaseHost));
        sb.append(String.format("repos.db.port=%d\n", reposDatabasePort));
        sb.append(String.format("repos.db.database=%s\n", reposDatabaseName));
        sb.append(String.format("repos.db.user=%s\n", reposDatabaseUser));
        sb.append(String.format("repos.db.passwd=%s\n", reposDatabasePasswd));
        sb.append("\n");
        sb.append(String.format("repos.local.du.reserved=%d\n", reposLocalDiskUsageReserved));
        sb.append("\n");
        sb.append(String.format("repos.socket.server.pool.size=%d\n", reposSocketServerPoolSize));
        sb.append(String.format("repos.socket.io.buff.size=%d\n", reposSocketIOBuffSize));
        sb.append(String.format("repos.socket.server.ip=%s\n", reposSocketServerIP));
        sb.append(String.format("repos.socket.server.port=%d\n", reposSocketServerPort));
        sb.append(String.format("repos.socket.server.timeout=%d\n", reposSocketServerTimeout));
        sb.append(String.format("repos.socket.client.timeout=%d\n", reposSocketClientTimeout));
        sb.append("\n");
        sb.append(String.format("repos.http.server.ip=%s\n", reposHttpServerIP));
        sb.append(String.format("repos.http.server.port=%d\n", reposHttpServerPort));
        sb.append("-------------------- Repository Config --------------------\n");
        return sb.toString();
    }

    private void loadConfig(InputStream is) throws IOException, NumberFormatException {
        Properties p = new Properties();
        p.load(is);
        // database
        reposDatabaseDriver = p.getProperty("repos.db.driver");
        reposDatabaseUri = p.getProperty("repos.db.uri");
        reposDatabaseHost = p.getProperty("repos.db.host");
        reposDatabasePort = Integer.parseInt(p.getProperty("repos.db.port"));
        reposDatabaseName = p.getProperty("repos.db.database");
        reposDatabaseUser = p.getProperty("repos.db.user");
        reposDatabasePasswd = p.getProperty("repos.db.passwd");
        // local
        reposLocalDiskUsageReserved = Long.parseLong(p.getProperty("repos.local.du.reserved"));
        // socket
        reposSocketServerPoolSize = Integer.parseInt(p.getProperty("repos.socket.server.pool.size"));
        reposSocketIOBuffSize = Integer.parseInt(p.getProperty("repos.socket.io.buff.size"));
        reposSocketServerIP = p.getProperty("repos.socket.server.ip");
        reposSocketServerPort = Integer.parseInt(p.getProperty("repos.socket.server.port"));
        reposSocketIOBuffSize = Integer.parseInt(p.getProperty("repos.socket.io.buff.size"));
        reposSocketServerTimeout = Integer.parseInt(p.getProperty("repos.socket.server.timeout"));
        reposSocketClientTimeout = Integer.parseInt(p.getProperty("repos.socket.client.timeout"));
        // http
        reposHttpServerIP = p.getProperty("repos.http.server.ip");
        reposHttpServerPort = Integer.parseInt(p.getProperty("repos.http.server.port"));
    }

    /*
     * TODO
     * 1. write error log
     * 2. exit application
     * 3. throw ReposException.create(log, e.getMessage());
     */
    public void loadProperties(String filepath) {
        InputStream is = null;
        try {
            is = new FileInputStream(filepath);
            loadConfig(is);
            is.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (NumberFormatException nfe) {
            nfe.printStackTrace();
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
